package api

import (
	"RedWork/dao"
	"RedWork/gdao"
	"RedWork/model"
	"RedWork/service"
	"RedWork/util"
	"RedWork/util/errmsg"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-sql-driver/mysql"
	"log"
	"math/rand"
	"strconv"
	"time"
)

func Userregiser() gin.HandlerFunc {
	return func(c *gin.Context) {
		errcode := errmsg.SUCCESS_REIGISTER
		status := true
		username := c.PostForm("username")
		password := c.PostForm("password")
		var user model.UserInfo
		user.UserName = username
		user.PassWord = password
		var uid int
		var err error
		if len(password) >= 6 {
			uid, err = gdao.AddUser(user)
			if err != nil {
				status = false
				fmt.Println("dao", err)
			}
			if driveErr, ok := err.(*mysql.MySQLError); ok {
				if driveErr.Number == 1062 {
					errcode = errmsg.ERROR_USERNAME_USED
				}
			}
		} else {
			status = false
			uid = 0
			errcode = errmsg.ERROR_USER_LENOFFW_LESS6
		}

		c.JSON(200, gin.H{
			"status": status,
			"data":   errmsg.GetErrMsg(errcode),
			"uid":    uid,
		})
	}
}

func EmailRegister() gin.HandlerFunc {
	return func(c *gin.Context) {
		email := c.PostForm("email")
		mailCenter := util.NewEmailCenter(&util.EmailConfig{
			ServerHost:   model.MailInfo.ServerHost,
			ServerPort:   25,
			FromEmail:    model.MailInfo.FromEmail,
			FromPassword: model.MailInfo.FromPassword,
		})

		hash := sha256.New()
		hash.Write([]byte(email + time.Now().String()))
		sum := hash.Sum(nil)
		toStringsha256 := hex.EncodeToString(sum)

		url := "http://127.0.0.1:8081/v1/user/userCenter/email/verify?email_token=" + toStringsha256
		service.RedisDB.Set(toStringsha256, email, time.Hour)
		data := "golightos邮箱注册，点击以下链接完成认证：" + url
		err := mailCenter.AddToers(email).SetMessage("", "golightos注册", data).Send()
		if err != nil {
			log.Println(err)
			return
		}
		c.JSON(200, gin.H{
			"status": true,
			"data":   "请前往邮箱查看",
		})
	}
}

func EmailVerify() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.Query("email_token")
		fmt.Println("EmailVerify token=", token)
		val, ok := service.RedisVal(token)
		fmt.Println("test email val", val)
		if ok {
			rand.Seed(time.Now().Unix())
			user, err := dao.AddUser(model.UserInfo{
				UserName: "temp" + strconv.Itoa(int(rand.Uint32())),
				PassWord: "",
				Email:    val,
			})
			if err != nil {
				c.JSON(401, gin.H{
					"status": false,
					"data":   "注册失败",
				})
				return
			}
			c.JSON(200, gin.H{
				"status": true,
				"data":   "id=" + strconv.Itoa(user),
			})
			err = service.RedisDEL(token)
			if err != nil {
				log.Println(err)
				return
			}
			return
		}
		c.JSON(401, gin.H{
			"data": "err!",
		})
	}
}

func UserLogin() gin.HandlerFunc {
	return func(c *gin.Context) {
		JwtKey := service.JWTKey{Key: []byte(service.PrivateKey)}
		status := true
		data := errmsg.GetErrMsg(errmsg.SUCCESS_LOGIN)
		token := ""
		uid := 0
		userna := c.PostForm("username")
		fmt.Println(userna)
		passwd := c.PostForm("password")
		dbPW, uid, err := gdao.QueryUserPW(userna)
		if err != nil {
			if _, ok := err.(*mysql.MySQLError); ok {
				status = false
				data = "数据库错误"
			}
		}
		if uid == 0 {
			status = false
			data = "没有此用户"
		} else if dbPW != passwd {
			status = false
			data = "用户名不存在或密码错误"
		} else {
			_, exist := service.RedisVal(strconv.Itoa(uid))
			if exist {
				status = false
				data = "用户已登录"
			}
		}
		if status != false {
			token, err = JwtKey.CreateToken(service.MyClaims{UserName: userna, UserID: uid})
			if err != nil {
				status = false
				data = "创建token失败"
			}
		}
		if status == true {
			//var expire time.Duration

			err = service.RedisDB.Set(strconv.Itoa(uid), token, time.Duration(7200)*time.Second).Err()
			if err != nil {
				fmt.Println("redis创建出错")
				data = "服务器内部错误"
				uid = 0
				status = false
				token = ""
			}
			c.SetCookie("uid", strconv.Itoa(uid), 7200, "/", c.ClientIP(), false, true)
		}
		c.JSON(200, gin.H{
			"status": status,
			"data":   data,
			"uid":    uid,
			"token":  token,
		})
	}
}

func Userloginout() gin.HandlerFunc {
	return func(c *gin.Context) {
		status := true
		data := ""
		userna := c.PostForm("username")
		token := c.PostForm("token")
		uid, err := dao.QueryUserID(userna)
		fmt.Println("用户想登出", uid, userna)
		if err != nil {
			status = false
			data = "非法登出"
			fmt.Println("dao.QueryUserID err", err)
		} else {
			val, ok := service.RedisVal(strconv.Itoa(uid))
			fmt.Println("登出者token是", val)
			fmt.Println("请求的token是", token)
			if !ok {
				fmt.Println("IF NoT OK")
				status = false
				data = errmsg.GetErrMsg(errmsg.ERROR_TOKEN_EXIST)
			} else {
				if val != token {
					status = false
					data = "NOT_RIGHT_TOKEN"
				}
			}

		}
		if status == true {
			errT := service.RedisDEL(strconv.Itoa(uid))

			if errT != nil {
				fmt.Println(errT)
			}
		}
		if status {
			fmt.Println("用户登出:", uid)
		}

		c.JSON(200, gin.H{
			"status": status,
			"data":   data,
		})
	}
}

func Recharge() gin.HandlerFunc {
	return func(c *gin.Context) {
		status := true
		data := ""
		code, _ := c.Get("token_code")
		if code != errmsg.SUCCSE {
			status = false
			c.JSON(200, gin.H{
				"status": status,
				"data":   errmsg.GetErrMsg(code.(int)),
			})
			c.Abort()
			return
		}
		uid, _ := c.Get("uid")
		uidint := uid.(int)
		money := c.PostForm("money")
		moneyf, err := strconv.ParseFloat(money, 64)
		if err != nil || moneyf > 5000 {
			fmt.Println(err)
			status = false
			data = "parm is not right"
		} else {
			err = gdao.AddMoney(uidint, money)
			if err != nil {
				status = false
				data = "数据库错误"
				_, _, errcode := util.ErrHandle(err)
				if errcode == 1264 {
					data = "用户可充值金额已达上限"
				}
			}
			if status {
				data = fmt.Sprintf("ID = %d用户，成功添加%.2f元！", uidint, moneyf)
			}
		}

		c.JSON(200, gin.H{
			"status": status,
			"data":   data,
		})
	}
}

func QueryUserInfo() gin.HandlerFunc {
	return func(c *gin.Context) {
		status := true
		data := ""
		code, _ := c.Get("token_code")
		if code != errmsg.SUCCSE {
			status = false
			c.JSON(200, gin.H{
				"status": status,
				"data":   errmsg.GetErrMsg(code.(int)),
			})
			c.Abort()
			return
		}
		uid, _ := c.Get("uid")
		uidint := uid.(int)
		user_id := c.Query("user_id")
		uidstr := strconv.Itoa(uidint)
		if uidstr != user_id {
			status = false
			data = errmsg.GetErrMsg(errmsg.ERROR_TOKEN_WRONG)
		}
		if !status {
			c.JSON(200, gin.H{
				"status": status,
				"data":   data,
			})
			c.Abort()
			return
		}
		c.JSON(200, gin.H{
			"status": status,
			"data":   dao.QueryUserInfo(uidstr),
		})
	}
}
